package com.lab.system.service.impl;

import com.lab.common.core.domain.entity.SysDept;
import com.lab.common.core.domain.entity.SysRole;
import com.lab.common.core.domain.entity.SysUser;
import com.lab.common.core.domain.model.LoginUser;
import com.lab.common.enums.LabStatus;
import com.lab.common.utils.StringUtils;
import com.lab.system.domain.Lab;
import com.lab.system.domain.LabBorrow;
import com.lab.system.domain.qo.LabQO;
import com.lab.system.mapper.LabBorrowMapper;
import com.lab.system.mapper.LabMapper;
import com.lab.system.mapper.SysDeptMapper;
import com.lab.system.mapper.SysUserMapper;
import com.lab.system.service.ILabService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 实验室Service业务层处理
 *
 * @author cf
 * @date 2025-02-09
 */
@Service
public class LabServiceImpl implements ILabService {
    @Autowired
    private LabMapper labMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private LabBorrowMapper labBorrowMapper;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 查询实验室
     *
     * @param id 实验室主键
     * @return 实验室
     */
    @Override
    public Lab selectLabById(Long id) {
        return labMapper.selectLabById(id);
    }

    /**
     * 查询实验室列表
     *
     * @param lab 实验室
     * @return 实验室
     */
    @Override
    public List<Lab> selectLabList(Lab lab, LoginUser loginUser) {
        // 控制数据权限
        List<SysRole> roles = loginUser.getUser().getRoles();
        List<Long> collect = roles.stream().map(SysRole::getRoleId).collect(Collectors.toList());
        if (!collect.contains(1L)) {
            lab.setCollegeId(loginUser.getDeptId());
        }
        // 批量查询学院
        List<Lab> labs = labMapper.selectLabList(lab);
        List<Long> collegeIds = labs.stream().map(Lab::getCollegeId).collect(Collectors.toList());
        List<SysDept> depts = new ArrayList<>();
        if (!collegeIds.isEmpty()) {
            depts = sysDeptMapper.selectDeptByIds(collegeIds);
        }
        Map<Long, String> deptMap = depts.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
        // 根据id查询老师
        List<String> teacherIds = labs.stream().map(Lab::getTeacherIds).collect(Collectors.toList());
        // 把所有的user_id收集起来
        Set<Long> teacherIdSet = new HashSet<>();
        teacherIds.forEach(x -> {
            if (StringUtils.isNotBlank(x)) {
                List<Long> ids = Arrays.stream(x.split(",")).map(Long::valueOf).collect(Collectors.toList());
                teacherIdSet.addAll(ids);
            }
        });
        Map<Long,String> userMap;
        if (!teacherIdSet.isEmpty()) {
            List<SysUser> sysUsers = userMapper.selectUserByIds(new ArrayList<>(teacherIdSet));
            userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
        } else {
            userMap = new HashMap<>();
        }
        labs.forEach(x -> {
            x.setCollegeName(deptMap.get(x.getCollegeId()));
            x.setStatusDesc(Objects.requireNonNull(LabStatus.getLabStatus(x.getStatus())).getInfo());

            if (StringUtils.isNotBlank(x.getTeacherIds())) {
                List<Long> teacherIdList = Arrays.stream(x.getTeacherIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
                // 通过userMap找到对应的名字，使用逗号拼接起来
                StringJoiner joiner = new StringJoiner(",");
                for (Long teacherId : teacherIdList) {
                    joiner.add(userMap.get(teacherId));
                }
                x.setTeacherNames(joiner.toString());
            }
        });
        return labs;
    }

    /**
     * 新增实验室
     *
     * @param lab 实验室
     * @return 结果
     */
    @Override
    public int insertLab(Lab lab) {
        return labMapper.insertLab(lab);
    }

    /**
     * 修改实验室
     *
     * @param lab 实验室
     * @return 结果
     */
    @Override
    public int updateLab(Lab lab) {
        return labMapper.updateLab(lab);
    }

    /**
     * 批量删除实验室
     *
     * @param ids 需要删除的实验室主键
     * @return 结果
     */
    @Override
    public int deleteLabByIds(Long[] ids) {
        return labMapper.deleteLabByIds(ids);
    }

    /**
     * 删除实验室信息
     *
     * @param id 实验室主键
     * @return 结果
     */
    @Override
    public int deleteLabById(Long id) {
        return labMapper.deleteLabById(id);
    }

    @Override
    public String generateLabNo() {
        //规则 LAB_ + 当前年份 + 当前月份 + 当前日期 + 随机数
        return "LAB" +
                String.format("%04d", Integer.parseInt(String.valueOf(System.currentTimeMillis()).substring(0, 4))) +
                String.format("%02d", Integer.parseInt(String.valueOf(System.currentTimeMillis()).substring(4, 6))) +
                String.format("%02d", Integer.parseInt(String.valueOf(System.currentTimeMillis()).substring(6, 8))) +
                String.format("%04d", (int) (Math.random() * 10000));
    }

    @Override
    public List<Lab> selectLabByLabQO(LabQO labQO) {
        Lab lab = new Lab();
        if (labQO.getLabName() != null) {
            lab.setLabName(labQO.getLabName());
        }
        if (labQO.getLabNo() != null) {
            lab.setLabNo(labQO.getLabNo());
        }
        boolean flag = lab.getLabNo() == null && lab.getLabName() == null;
        List<Lab> labs = labMapper.selectLabList(lab);
        List<Long> labIds = labs.stream().map(Lab::getId).collect(Collectors.toList());
        // 查询条件都为空不查
        List<LabBorrow> labBorrows;
        if (labQO.getStartTime() != null || labQO.getEndTime() != null || labQO.getLabNo() != null || labQO.getLabName() != null) {
            // 开始时间和结束时间在借出时间段内的实验室，需要过滤掉
            labBorrows = labBorrowMapper.selectLabBorrowList(LabBorrow
                    .builder()
                    .startTime(labQO.getStartTime())
                    .endTime(labQO.getEndTime())
                    .labIds(flag ? null : labIds)
                    .build());
        } else {
            labBorrows = new ArrayList<>();
        }

        // 过滤掉已借出实验室
        labs = labs.stream().filter(x -> labBorrows.stream().noneMatch(y -> y.getLabId().equals(x.getId()))).collect(Collectors.toList());
        return labs;
    }
}
